package com.xhs.hawaii.framework.thrift;

import com.xhs.hawaii.common.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.pool.BasePoolableObjectFactory;
import org.apache.thrift.TServiceClient;
import org.apache.thrift.TServiceClientFactory;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TFramedTransport;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;

import java.net.InetSocketAddress;

/**
 * @author tangchuang
 * @version 1.0
 * @since 2018/1/20
 */
@Slf4j
public class ThriftClientFactory extends BasePoolableObjectFactory<TServiceClient> {

    private TServiceClientFactory<TServiceClient> clientFactory;
    private ThriftServerAddressContainer thriftServerAddressContainer;

    public ThriftClientFactory(TServiceClientFactory<TServiceClient> clientFactory, ThriftServerAddressContainer thriftServerAddressContainer) {
        this.clientFactory = clientFactory;
        this.thriftServerAddressContainer = thriftServerAddressContainer;
    }

    @Override
    public TServiceClient makeObject() throws Exception {
        InetSocketAddress address = thriftServerAddressContainer.selector();
        if (address == null) {
            throw new BusinessException("No provider available for remote api");
        }
        TSocket tsocket = new TSocket(address.getHostName(), address.getPort());
        TTransport transport = new TFramedTransport(tsocket);
        TProtocol protocol = new TBinaryProtocol(transport);
        TServiceClient client = this.clientFactory.getClient(protocol);
        transport.open();
        return client;
    }

    @Override
    public void destroyObject(TServiceClient client) throws Exception {
        log.info("destroyObject:{}", client);
        TTransport pin = client.getInputProtocol().getTransport();
        pin.close();
        TTransport pout = client.getOutputProtocol().getTransport();
        pout.close();
    }

    @Override
    public boolean validateObject(TServiceClient client) {
        TTransport pin = client.getInputProtocol().getTransport();
        log.info("validateObject input:{}", pin.isOpen());
        TTransport pout = client.getOutputProtocol().getTransport();
        log.info("validateObject output:{}", pout.isOpen());
        return pin.isOpen() && pout.isOpen();
    }
}
